home *** CD-ROM | disk | FTP | other *** search
- //=============================================================================
- //
- // Copyright (C) 1995, 1996 by Paul S. McCarthy and Eric Sunshine.
- // Written by Paul S. McCarthy and Eric Sunshine.
- // All Rights Reserved.
- //
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the authors
- // and its use is governed by the MiscKit license, found in the file
- // "License.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
- //=============================================================================
- //-----------------------------------------------------------------------------
- // MiscTableScrollSort.M
- //
- // Sorting support for MiscTableScroll.
- //
- // FIXME: OPTIMIZATION -- Don't make a function call to do the comparisons
- // unless the user has installed a custom sort function. Use a big
- // switch statement. (This eliminates one function call per comparison.)
- //
- // FIXME: OPTIMIZATION -- Pre-compute the method that will be used to access
- // the values in each slot. We should not need to keep testing whether
- // or not the delegate / dataDelegate -respondTo: tableScroll:intValueAt::
- // for instance. Figure this stuff out ahead of time, and store the
- // information in the MiscSlotSortInfo structure somewhere. (This can
- // eliminate somewhere around 4-6 function calls per comparison.)
- //
- // FIXME: OPTIMIZATION -- Consider re-using the sort info objects at least to
- // avoid allocating and freeing entry_info[] and buff[] all the time.
- // Consider embedding one of them right in the table-scroll itself.
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // $Id: MiscTableScrollSort.M,v 1.2 96/02/12 00:06:06 sunshine Exp $
- // $Log: MiscTableScrollSort.M,v $
- // Revision 1.2 96/02/12 00:06:06 sunshine
- // Fixed bug where -border:setSlot:sortType: was ignoring case-sensitive
- // title, case-insensitive title, state, and unsigned state sort types. This
- // resulted in the default -stringValue variation to be used for those slots,
- // which is clearly incorrect.
- //
- // Revision 1.1 96/01/13 23:31:59 zarnuk
- // Split-off from MiscTableScroll to ease maintenance.
- // Now pre-computes more sorting information.
- // Now has builtin median-of-three quick sort function.
- // (Much closer to being re-entrant and thread-safe now).
- // Now uses cell coordinates instead of cell-pointers for cell-wise compare.
- // Now handles single-buffered lazy tables. (bug fix).
- // Now uses ...ValueAt:: methods to enhance performance of lazy tables.
- // Added new methods: -slotsAreSorted:, -border:slotIsSorted:,
- // -border:compareSlots::
- //-----------------------------------------------------------------------------
- #import <misckit/MiscTableScroll.h>
- #import "MiscTableBorder.h"
-
- extern "C" {
- #import <assert.h>
- #import <stdlib.h>
- #import <strings.h>
- }
-
- //=============================================================================
- // CELL-VALUE ACCESS
- //=============================================================================
-
- //-----------------------------------------------------------------------------
- // copy_string
- //-----------------------------------------------------------------------------
- static char* copy_string( char const* s, MiscSlotSortInfo* info )
- {
- int len = strlen( s ) + 1;
- int sz = info->buff_size;
- char* t = info->buff;
- if (sz < len)
- {
- do { sz += 256; } while (sz < len);
- NXZone* const z = info->zone;
- if (t == 0)
- t = (char*) NXZoneMalloc( z, sz );
- else
- t = (char*) NXZoneRealloc( z, t, sz );
- info->buff_size = sz;
- info->buff = t;
- }
- memcpy( t, s, len );
- return t;
- }
-
-
- //-----------------------------------------------------------------------------
- // cell_str
- //-----------------------------------------------------------------------------
- static inline char const* cell_str( int r, int c,
- MiscSlotSortInfo* info, BOOL make_copy )
- {
- char const* t = [info->table_scroll stringValueAt:r:c];
- if (t == 0)
- t = "";
- else if (make_copy)
- t = copy_string( t, info );
- return t;
- }
-
-
- //-----------------------------------------------------------------------------
- // cell_title
- //-----------------------------------------------------------------------------
- static inline char const* cell_title( int r, int c,
- MiscSlotSortInfo* info, BOOL make_copy )
- {
- char const* t = [info->table_scroll titleAt:r:c];
- if (t == 0)
- t = "";
- else if (make_copy)
- t = copy_string( t, info );
- return t;
- }
-
-
- //-----------------------------------------------------------------------------
- // cell_int
- //-----------------------------------------------------------------------------
- static inline int cell_int( int r, int c, MiscSlotSortInfo const* info )
- {
- return ([info->table_scroll intValueAt:r:c]);
- }
-
-
- //-----------------------------------------------------------------------------
- // cell_state
- //-----------------------------------------------------------------------------
- static inline int cell_state( int r, int c, MiscSlotSortInfo const* info )
- {
- return ([info->table_scroll stateAt:r:c]);
- }
-
-
- //-----------------------------------------------------------------------------
- // cell_tag
- //-----------------------------------------------------------------------------
- static inline int cell_tag( int r, int c, MiscSlotSortInfo const* info )
- {
- return ([info->table_scroll tagAt:r:c]);
- }
-
-
- //-----------------------------------------------------------------------------
- // cell_float
- //-----------------------------------------------------------------------------
- static inline float cell_float( int r, int c, MiscSlotSortInfo const* info )
- {
- return ([info->table_scroll floatValueAt:r:c]);
- }
-
-
- //-----------------------------------------------------------------------------
- // cell_double
- //-----------------------------------------------------------------------------
- static inline double cell_double( int r, int c, MiscSlotSortInfo const* info )
- {
- return ([info->table_scroll doubleValueAt:r:c]);
- }
-
-
- //=============================================================================
- // CELL COMPARISON FUNCTIONS
- //=============================================================================
-
- //-----------------------------------------------------------------------------
- // cmp_ititle
- //-----------------------------------------------------------------------------
- static int cmp_ititle( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo* info )
- {
- char const* const s1 = cell_title( r1,c1,info,info->need_copy );
- char const* const s2 = cell_title( r2,c2,info,NO );
- // FIXME: Use NXOrderStrings() here.
- return strcasecmp( s1, s2 );
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_title
- //-----------------------------------------------------------------------------
- static int cmp_title( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo* info )
- {
- char const* const s1 = cell_title( r1,c1,info,info->need_copy );
- char const* const s2 = cell_title( r2,c2,info,NO );
- return strcmp( s1, s2 );
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_state
- //-----------------------------------------------------------------------------
- static int cmp_state( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo const* info )
- {
- int const x1 = cell_state(r1,c1,info);
- int const x2 = cell_state(r2,c2,info);
- if (x1 < x2)
- return -1;
- if (x1 > x2)
- return 1;
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_ustate
- //-----------------------------------------------------------------------------
- static int cmp_ustate( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo const* info )
- {
- unsigned int const x1 = (unsigned int) cell_state(r1,c1,info);
- unsigned int const x2 = (unsigned int) cell_state(r2,c2,info);
- if (x1 < x2)
- return -1;
- if (x1 > x2)
- return 1;
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_istr
- //-----------------------------------------------------------------------------
- static int cmp_istr( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo* info )
- {
- char const* const s1 = cell_str( r1,c1,info,info->need_copy );
- char const* const s2 = cell_str( r2,c2,info,NO );
- // FIXME: Use NXOrderStrings() here.
- return strcasecmp( s1, s2 );
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_str
- //-----------------------------------------------------------------------------
- static int cmp_str( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo* info )
- {
- char const* const s1 = cell_str( r1,c1,info,info->need_copy );
- char const* const s2 = cell_str( r2,c2,info,NO );
- return strcmp( s1, s2 );
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_int
- //-----------------------------------------------------------------------------
- static int cmp_int( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo const* info )
- {
- int const x1 = cell_int(r1,c1,info);
- int const x2 = cell_int(r2,c2,info);
- if (x1 < x2)
- return -1;
- if (x1 > x2)
- return 1;
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_uint
- //-----------------------------------------------------------------------------
- static int cmp_uint( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo const* info )
- {
- unsigned int const x1 = (unsigned int) cell_int(r1,c1,info);
- unsigned int const x2 = (unsigned int) cell_int(r2,c2,info);
- if (x1 < x2)
- return -1;
- if (x1 > x2)
- return 1;
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_tag
- //-----------------------------------------------------------------------------
- static int cmp_tag( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo const* info )
- {
- int const x1 = cell_tag(r1,c1,info);
- int const x2 = cell_tag(r2,c2,info);
- if (x1 < x2)
- return -1;
- if (x1 > x2)
- return 1;
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_utag
- //-----------------------------------------------------------------------------
- static int cmp_utag( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo const* info )
- {
- unsigned int const x1 = (unsigned int) cell_tag(r1,c1,info);
- unsigned int const x2 = (unsigned int) cell_tag(r2,c2,info);
- if (x1 < x2)
- return -1;
- if (x1 > x2)
- return 1;
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_float
- //-----------------------------------------------------------------------------
- static int cmp_float( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo const* info )
- {
- float const x1 = cell_float(r1,c1,info);
- float const x2 = cell_float(r2,c2,info);
- if (x1 < x2)
- return -1;
- if (x1 > x2)
- return 1;
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_double
- //-----------------------------------------------------------------------------
- static int cmp_double( int r1, int c1, int r2, int c2,
- MiscSlotSortInfo const* info )
- {
- double const x1 = cell_double(r1,c1,info);
- double const x2 = cell_double(r2,c2,info);
- if (x1 < x2)
- return -1;
- if (x1 > x2)
- return 1;
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // cmp_skip
- //-----------------------------------------------------------------------------
- static int cmp_skip( int,int,int,int,MiscSlotSortInfo const*)
- {
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // COMPARE_FUNC[]
- //-----------------------------------------------------------------------------
- static MiscCompareEntryFunc const COMPARE_FUNC[ MISC_SORT_TYPE_MAX + 1 ] =
- {
- cmp_istr,
- cmp_str,
- cmp_int,
- cmp_uint,
- cmp_tag,
- cmp_utag,
- cmp_float,
- cmp_double,
- cmp_skip,
- cmp_ititle,
- cmp_title,
- cmp_state,
- cmp_ustate
- };
-
-
- //=============================================================================
- // SLOT-COMPARE
- //=============================================================================
- //-----------------------------------------------------------------------------
- // MiscDefaultCompareSlotFunc
- //-----------------------------------------------------------------------------
- int MiscDefaultCompareSlotFunc(
- int slot1,
- int slot2,
- MiscSlotSortInfo* info )
- {
- int rc = 0;
- MiscEntrySortInfo const* p = info->entry_info;
- MiscEntrySortInfo const* const plim = p + info->num_entries;
-
- if (info->border_type == MISC_COL_BORDER) // Row-wise compare
- {
- for ( ; p < plim; p++)
- {
- int const col = p->slot;
- if ((rc = (*(p->compare_func))(slot1,col,slot2,col,info)) != 0)
- return (p->ascending ? rc : -rc);
- }
- }
- else // Col-wise compare
- {
- for ( ; p < plim; p++)
- {
- int const row = p->slot;
- if ((rc = (*(p->compare_func))(row,slot1,row,slot2,info)) != 0)
- return (p->ascending ? rc : -rc);
- }
- }
-
- return 0;
- }
-
-
-
- //=============================================================================
- // QSORT
- //=============================================================================
-
- //-----------------------------------------------------------------------------
- // swap
- //-----------------------------------------------------------------------------
- inline static void swap( int x, int y, int a[] )
- {
- int t = a[x];
- a[x] = a[y];
- a[y] = t;
- }
-
-
- //-----------------------------------------------------------------------------
- // do_qsort
- //-----------------------------------------------------------------------------
- static void do_qsort(
- int a[],
- int N,
- MiscCompareSlotFunc f,
- MiscSlotSortInfo* info )
- {
- assert( N > 1 );
-
- int const STACK_MAX = 64; // log_base_2(ULNG_MAX) * 2
- int stk[ STACK_MAX ];
- int top = 0;
- int left = 0;
- int right = N - 1; // WARNING: N == 0
- int i,j,n; // minus one is HUGE value.
-
- for (;;)
- {
- while (right > left)
- {
- n = (right - left) + 1; // right,left bounds are inclusive.
- if (n >= 3)
- {
- int mid = (left + right) >> 1;
- if ((*f)(a[left],a[right],info) > 0) swap(left,right,a);
- if ((*f)(a[mid], a[right],info) > 0) swap(mid,right,a);
- if ((*f)(a[left],a[mid], info) > 0) swap(left,mid,a);
- if (n == 3) break;
- right--;
- swap(mid,right,a);
- int v = a[right];
- i = left;
- j = right;
- for (;;)
- {
- while ((*f)(a[++i],v,info) < 0) /* empty */;
- while ((*f)(a[--j],v,info) > 0) /* empty */;
- if (i >= j) break;
- swap( i, j, a );
- }
- swap( i, right, a );
- right++;
- if (i - left > right - i)
- { stk[top++] = left; stk[top++] = i-1; left = i+1; }
- else if (right - i > 1)
- { stk[top++] = i+1; stk[top++] = right; right = i-1; }
- else
- break;
- }
- else // (n < 3)
- {
- if (n > 1) // && (n < 3)
- {
- if ((*f)(a[left],a[right],info) > 0)
- swap(left,right,a);
- }
- break;
- }
- }
- if (top == 0) break;
- right = stk[--top];
- left = stk[--top];
- }
- }
-
-
- @implementation MiscTableScroll(Sort)
-
- //-----------------------------------------------------------------------------
- // - compareSlotFunc
- //-----------------------------------------------------------------------------
- - (MiscCompareSlotFunc) compareSlotFunc
- {
- return sort_slot_func ? sort_slot_func : MiscDefaultCompareSlotFunc;
- }
-
-
- //-----------------------------------------------------------------------------
- // - setCompareSlotFunc:
- //-----------------------------------------------------------------------------
- - (void) setCompareSlotFunc: (MiscCompareSlotFunc) f
- {
- sort_slot_func = (f ? f : MiscDefaultCompareSlotFunc);
- }
-
-
- //-----------------------------------------------------------------------------
- // - sortInfoInit:border:
- //-----------------------------------------------------------------------------
- - (void) sortInfoInit:(MiscSlotSortInfo*)ip border:(MiscBorderType)b
- {
- MiscBorderType const ob = MISC_OTHER_BORDER(b);
- MiscTableBorder* const obp = info[ob]->border;
- NXZone* const z = [self zone];
-
- ip->table_scroll = self;
- ip->zone = z;
- ip->border_type = ob;
- ip->num_entries = 0;
- ip->entry_info = 0;
- ip->need_copy = lazy && ([self buffCount] < 2);
- ip->buff = 0;
- ip->buff_size = 0;
-
- int M; // Number of "cols".
- int const* v = [self slotSortVector:ob len:&M];
- if (v == 0 || M == 0)
- {
- v = obp->getPMap();
- M = obp->count();
- }
-
- if (M > 0)
- {
- MiscEntrySortInfo* ep = (MiscEntrySortInfo*)
- NXZoneMalloc( z, M * sizeof(*ep) );
-
- if (ep != 0)
- {
- ip->num_entries = M;
- ip->entry_info = ep;
-
- int j = 0;
- for (int i = 0; i < M; i++)
- {
- MiscEntrySortInfo& r = ep[j++];
- int n = (v ? v[i] : i);
- BOOL was_neg = (n < 0);
- if (was_neg)
- n = -n;
- r.slot = n;
- if ([self border:ob slotSortDirection:n]==MISC_SORT_DESCENDING)
- was_neg = !was_neg;
- r.ascending = !was_neg;
- if ((r.compare_func = [self border:ob slotSortFunc:n]) == 0)
- {
- MiscSortType t = [self border:ob slotSortType:n];
- if ((unsigned int)t <= (unsigned int)MISC_SORT_TYPE_MAX &&
- t != MISC_SORT_SKIP)
- {
- r.sort_type = t;
- r.compare_func = COMPARE_FUNC[t];
- }
- else // No custom function, and sort-type == skip.
- {
- j--; // Do not include this slot.
- }
- }
- else
- r.sort_type = MISC_SORT_CUSTOM;
- }
- ip->num_entries = j; // Number of non-skip slots.
- }
- else
- {
- [self error:"Memory allocation failure.\n"];
- }
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // - sortInfoDone:
- //-----------------------------------------------------------------------------
- - (void) sortInfoDone:(MiscSlotSortInfo*)ip
- {
- if (ip->entry_info != 0)
- { // Cast off const-ness.
- NXZoneFree( ip->zone, (MiscEntrySortInfo*) ip->entry_info );
- ip->entry_info = 0;
- }
- if (ip->buff != 0)
- {
- free( ip->buff );
- ip->buff = 0;
- ip->buff_size = 0;
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // - sortSlots:
- //-----------------------------------------------------------------------------
- - (void) sortSlots:(MiscBorderType) b
- {
- int const N = [self numSlots:b]; // Number of "rows"
-
- if (N > 1)
- {
- MiscSlotSortInfo sort_info;
- [self sortInfoInit:&sort_info border:b];
- if (sort_info.num_entries > 0)
- {
- NXZone* const z = [self zone];
- int* const new_v2p = (int*) NXZoneMalloc( z, N * sizeof(int) );
- if (new_v2p != 0)
- {
- for (int j = 0; j < N; j++)
- new_v2p[j] = j;
-
- do_qsort( new_v2p, N, [self compareSlotFunc], &sort_info );
-
- info[b]->border->setPMap( new_v2p );
-
- [self update];
- NXZoneFree( z, new_v2p );
- }
- else
- {
- [self error:"Memory allocation failure.\n" ];
- }
- }
- [self sortInfoDone:&sort_info];
- }
- }
-
- - (void) sortCols { [self sortSlots:MISC_COL_BORDER]; }
- - (void) sortRows { [self sortSlots:MISC_ROW_BORDER]; }
-
-
- //-----------------------------------------------------------------------------
- // - border:compareSlots::info:
- //-----------------------------------------------------------------------------
- - (int) border:(MiscBorderType)b compareSlots:(int)slot1 :(int)slot2
- info:(MiscSlotSortInfo*)ip
- {
- return (*[self compareSlotFunc])( slot1, slot2, ip );
- }
-
- - (int) compareCols:(int)c1 :(int)c2 info:(MiscSlotSortInfo*)ip
- { return [self border:MISC_COL_BORDER compareSlots:c1:c2 info:ip]; }
- - (int) compareRows:(int)r1 :(int)r2 info:(MiscSlotSortInfo*)ip
- { return [self border:MISC_ROW_BORDER compareSlots:r1:r2 info:ip]; }
-
-
- //-----------------------------------------------------------------------------
- // - border:compareSlots::
- //-----------------------------------------------------------------------------
- - (int) border:(MiscBorderType)b compareSlots:(int)slot1 :(int)slot2
- {
- int rc = 0;
- MiscSlotSortInfo sort_info;
- [self sortInfoInit:&sort_info border:b];
- if (sort_info.num_entries > 0)
- rc = [self border:b compareSlots:slot1:slot2 info:&sort_info];
- [self sortInfoDone:&sort_info];
- return rc;
- }
-
- - (int) compareCols:(int)c1 :(int)c2
- { return [self border:MISC_COL_BORDER compareSlots:c1:c2]; }
- - (int) compareRows:(int)r1 :(int)r2
- { return [self border:MISC_ROW_BORDER compareSlots:r1:r2]; }
-
-
- //-----------------------------------------------------------------------------
- // - border:sortSlot:
- //-----------------------------------------------------------------------------
- - (BOOL) border:(MiscBorderType)b sortSlot:(int)pslot
- {
- BOOL moved = NO;
-
- int const N = [self numSlots:b]; // Number of "rows"
-
- if (N > 1)
- {
- MiscSlotSortInfo sort_info;
- [self sortInfoInit:&sort_info border:b];
- if (sort_info.num_entries > 0)
- {
- MiscCompareSlotFunc func = [self compareSlotFunc];
-
- int const vslot = [self border:b slotPosition:pslot];
- int const prev = (vslot > 0 ?
- [self border:b slotAtPosition:vslot - 1] : -1);
- int const next = (vslot < N - 1 ?
- [self border:b slotAtPosition:vslot + 1] : N);
-
- int lo = vslot;
- int hi = vslot - 1;
-
- if (prev >= 0 && (*func)( pslot, prev, &sort_info ) < 0)
- {
- lo = 0;
- hi = vslot - 2;
- }
- else if (next < N && (*func)( pslot, next, &sort_info) > 0)
- {
- lo = vslot + 1;
- hi = N - 1;
- }
-
- while (lo <= hi) // Binary search.
- {
- int const mid = (lo + hi) >> 1;
- int const n = [self border:b slotAtPosition:mid];
- int const cmp = (*func)( pslot, n, &sort_info );
- if (cmp < 0)
- hi = mid - 1;
- else
- lo = mid + 1;
- }
-
- if (lo != vslot)
- {
- [self border:b moveSlotFrom:vslot to:lo];
- [self update];
- moved = YES;
- }
- }
- [self sortInfoDone:&sort_info];
- }
-
- return moved;
- }
-
- - (BOOL) sortCol:(int)n { return [self border:MISC_COL_BORDER sortSlot:n]; }
- - (BOOL) sortRow:(int)n { return [self border:MISC_ROW_BORDER sortSlot:n]; }
-
-
- //-----------------------------------------------------------------------------
- // - slotsAreSorted:
- //-----------------------------------------------------------------------------
- - (BOOL) slotsAreSorted:(MiscBorderType)b
- {
- BOOL sorted = YES;
- int const N = [self numSlots:b]; // Number of "rows".
-
- if (N > 1)
- {
- MiscSlotSortInfo data;
- [self sortInfoInit:&data border:b];
- if (data.num_entries > 0)
- {
- MiscCompareSlotFunc func = [self compareSlotFunc];
- for (int i = 1; i < N; i++)
- if ((*func)( i - 1, i, &data ) > 0)
- {
- sorted = NO;
- break;
- }
- }
- [self sortInfoDone:&data];
- }
-
- return sorted;
- }
-
- - (BOOL) colsAreSorted { return [self slotsAreSorted:MISC_COL_BORDER]; }
- - (BOOL) rowsAreSorted { return [self slotsAreSorted:MISC_ROW_BORDER]; }
-
-
- //-----------------------------------------------------------------------------
- // - border:slotIsSorted:
- //-----------------------------------------------------------------------------
- - (BOOL) border:(MiscBorderType)b slotIsSorted:(int)pslot
- {
- BOOL sorted = YES;
- int const N = [self numSlots:b]; // Number of "rows".
-
- if (N > 1)
- {
- MiscSlotSortInfo data;
- [self sortInfoInit:&data border:b];
- if (data.num_entries > 0)
- {
- MiscCompareSlotFunc func = [self compareSlotFunc];
-
- int const vslot = [self border:b slotPosition:pslot];
- int const prev = (vslot > 0 ?
- [self border:b slotAtPosition:vslot - 1] : -1);
- int const next = (vslot < N - 1 ?
- [self border:b slotAtPosition:vslot + 1] : N);
-
- if (prev >= 0 && (*func)( prev, pslot, &data ) > 0)
- sorted = NO;
-
- else if (next < N && (*func)( pslot, next, &data ) > 0)
- sorted = NO;
- }
- [self sortInfoDone:&data];
- }
-
- return sorted;
- }
-
- - (BOOL) colIsSorted:(int)n
- { return [self border:MISC_COL_BORDER slotIsSorted:n]; }
- - (BOOL) rowIsSorted:(int)n
- { return [self border:MISC_ROW_BORDER slotIsSorted:n]; }
-
-
- //-----------------------------------------------------------------------------
- // autoSort
- //-----------------------------------------------------------------------------
- - (BOOL) autoSortSlots:(MiscBorderType)b
- { return info[b]->autoSort; }
- - (void) border:(MiscBorderType)b setAutoSortSlots:(BOOL)flag
- { info[b]->autoSort = flag; }
-
- - (BOOL) autoSortCols
- { return [self autoSortSlots:MISC_COL_BORDER]; }
- - (void) setAutoSortCols:(BOOL)flag
- { [self border:MISC_COL_BORDER setAutoSortSlots:flag]; }
-
- - (BOOL) autoSortRows
- { return [self autoSortSlots:MISC_ROW_BORDER]; }
- - (void) setAutoSortRows:(BOOL)flag
- { [self border:MISC_ROW_BORDER setAutoSortSlots:flag]; }
-
-
- //-----------------------------------------------------------------------------
- // Sort Vector
- //-----------------------------------------------------------------------------
- - (int const*) slotSortVector:(MiscBorderType)b len:(int*)len
- {
- MiscBorderInfo* const ip = info[b];
- *len = ip->sort_vector_len;
- return ip->sort_vector;
- }
-
- - (void) border:(MiscBorderType)b setSlotSortVector:(int const*)v len:(int)n
- {
- NXZone* const z = [self zone];
- MiscBorderInfo* const ip = info[b];
- if (ip->sort_vector != 0)
- NXZoneFree( z, ip->sort_vector );
- if (n > 0)
- {
- int const nbytes = n * sizeof(*v);
- ip->sort_vector_len = n;
- ip->sort_vector = (int*) NXZoneMalloc( z, nbytes );
- memcpy( ip->sort_vector, v, nbytes );
- }
- else
- {
- ip->sort_vector_len = 0;
- ip->sort_vector = 0;
- }
- }
-
- - (int const*) colSortVectorLen:(int*)len
- { return [self slotSortVector:MISC_COL_BORDER len:len]; }
- - (void) setColSortVector:(int const*)v len:(int)n;
- { [self border:MISC_COL_BORDER setSlotSortVector:v len:n]; }
-
- - (int const*) rowSortVectorLen:(int*)len
- { return [self slotSortVector:MISC_ROW_BORDER len:len]; }
- - (void) setRowSortVector:(int const*)v len:(int)n;
- { [self border:MISC_ROW_BORDER setSlotSortVector:v len:n]; }
-
-
-
- //-----------------------------------------------------------------------------
- // Sort Func
- //-----------------------------------------------------------------------------
- - (MiscCompareEntryFunc) border:(MiscBorderType)b slotSortFunc:(int)n
- { return info[b]->border->getSortFunc_P(n); }
- - (void) border:(MiscBorderType)b setSlot:(int)n
- sortFunc:(MiscCompareEntryFunc)x
- { info[b]->border->setSortFunc_P(n,x); }
-
- - (MiscCompareEntryFunc) colSortFunc:(int)n
- { return [self border:MISC_COL_BORDER slotSortFunc:n]; }
- - (void) setCol:(int)n sortFunc:(MiscCompareEntryFunc)x
- { [self border:MISC_COL_BORDER setSlot:n sortFunc:x]; }
-
- - (MiscCompareEntryFunc) rowSortFunc:(int)n
- { return [self border:MISC_ROW_BORDER slotSortFunc:n]; }
- - (void) setRow:(int)n sortFunc:(MiscCompareEntryFunc)x
- { [self border:MISC_ROW_BORDER setSlot:n sortFunc:x]; }
-
-
- //-----------------------------------------------------------------------------
- // Sort Direction
- //-----------------------------------------------------------------------------
- - (MiscSortDirection) border:(MiscBorderType)b slotSortDirection:(int)n
- { return info[b]->border->getSortDirection_P(n); }
- - (void) border:(MiscBorderType)b setSlot:(int)n
- sortDirection:(MiscSortDirection)x
- {
- if ((unsigned int) x <= (unsigned int) MISC_SORT_DESCENDING)
- info[b]->border->setSortDirection_P(n,x);
- }
-
- - (MiscSortDirection) colSortDirection:(int)n
- { return [self border:MISC_COL_BORDER slotSortDirection:n]; }
- - (void) setCol:(int)n sortDirection:(MiscSortDirection)x
- { [self border:MISC_COL_BORDER setSlot:n sortDirection:x]; }
-
- - (MiscSortDirection) rowSortDirection:(int)n
- { return [self border:MISC_ROW_BORDER slotSortDirection:n]; }
- - (void) setRow:(int)n sortDirection:(MiscSortDirection)x
- { [self border:MISC_ROW_BORDER setSlot:n sortDirection:x]; }
-
-
- //-----------------------------------------------------------------------------
- // Sort Type
- //-----------------------------------------------------------------------------
- - (MiscSortType) border:(MiscBorderType)b slotSortType:(int)n;
- { return info[b]->border->getSortType_P(n); }
- - (void) border:(MiscBorderType)b setSlot:(int)n
- sortType:(MiscSortType)x
- {
- if ((unsigned int) x <= (unsigned int) MISC_SORT_TYPE_MAX)
- info[b]->border->setSortType_P(n,x);
- }
-
- - (MiscSortType) colSortType:(int)n
- { return [self border:MISC_COL_BORDER slotSortType:n]; }
- - (void) setCol:(int)n sortType:(MiscSortType)x
- { [self border:MISC_COL_BORDER setSlot:n sortType:x]; }
-
- - (MiscSortType) rowSortType:(int)n
- { return [self border:MISC_ROW_BORDER slotSortType:n]; }
- - (void) setRow:(int)n sortType:(MiscSortType)x
- { [self border:MISC_ROW_BORDER setSlot:n sortType:x]; }
-
- @end
-